#include "TopMarkObject.h"

OBJECT_DEFINE_START (TopMarkObject, top_mark_object)

void
top_mark_object_init (TopMarkObject* obj)
{
        object_node_init (OBJECT_NODE (obj));
        object_set_destory_func (obj, top_mark_object_destory);
        obj->label_head    = NULL;
        obj->label_table   = NULL;
        obj->top_mark_name = NULL;
        obj->type          = TOP_MARK_TYPE_OTHER;
}

void
top_mark_object_destruction (TopMarkObject* obj)
{
        object_unref (obj->label_head);
        object_unref (obj->label_table);
        object_unref (obj->top_mark_name);
        object_node_destruction (OBJECT_NODE (obj));
}

static void
top_mark_object_add_label (TopMarkObject* obj, LabelObject* label)
{
        if (!obj || !label) {
                OBJECT_ERROR_TOOL (
                        TopMarkObject,
                        add_label,
                        "传入参数错误！TopMarkObject<%p>，LabelObject<%p>\n",
                        obj,
                        label);
                return;
        }

        if (!obj->label_head) {
                obj->label_head = object_reference_to (label, LABEL_OBJECT);
                object_node_set_as_manager (OBJECT_NODE (label));
                return;
        }
        object_node_set_new_end (OBJECT_NODE (obj->label_head),
                                 object_reference_to (label, OBJECT_NODE));
}

void
top_mark_object_register (TopMarkObject* obj,
                          const char*    label_key_name,
                          ValueType      type)
{
        if (!obj || !label_key_name || type == VALUE_TYPE_ERROR) {
                OBJECT_ERROR_TOOL (TopMarkObject,
                                   register,
                                   "传入参数有误！TopMarkObject<%p>, "
                                   "label_key_name<%p>, ValueType[%d]\n",
                                   obj,
                                   label_key_name,
                                   type);
                return;
        }
        if (!obj->label_table)
                obj->label_table = object_hash_new ();
        object_hash_set_value (obj->label_table,
                               label_key_name,
                               false,
                               O_PTR (type),
                               NULL);
}

int
top_mark_object_analysis_keyvalue_line (TopMarkObject*           obj,
                                        ObjectStringApplication* kvline)
{
        int                      state;
        ObjectStringApplication *key, *value;
        ValueType                value_type;
        LabelObject*             tmp;

        if (!obj || !kvline) {
                OBJECT_ERROR_TOOL (TopMarkObject,
                                   analysis_keyvalue_line,
                                   "参数传入错误！TopMarkObject<%p>"
                                   "，ObjectStringApplication<%p>\n",
                                   obj,
                                   kvline);
                return 1;
        }

        if (!obj->label_table) {
                OBJECT_ERROR_TOOL (
                        TopMarkObject,
                        analysis_keyvalue_line,
                        "尚未注册任何一组 LabelObject！请使用 "
                        "top_mark_object_register () 注册后再使用。\n");
                return 1;
        }

        object_string_application_set_segment_charset (kvline, '=');
        object_string_application_rewind (kvline);
        key   = object_string_application_get_string_before_segment (kvline);
        value = object_string_application_get_string_before_segment (kvline);
        if (!key || !value) {
                OBJECT_ERROR_TOOL (
                        TopMarkObject,
                        analysis_keyvalue_line,
                        "拆分等号时出现错误！原始字符串: '%s'\n",
                        object_string_get_string (OBJECT_STRING (kvline)));
                object_unref (key);
                object_unref (value);
                return 1;
        }
        /*净化前后空格*/
        object_string_purify_space (OBJECT_STRING (key));
        object_string_purify_space (OBJECT_STRING (value));

        value_type = (ValueType)object_hash_get_value (
                obj->label_table,
                object_string_get_string (OBJECT_STRING (key)),
                false);
        if (value_type == VALUE_TYPE_ERROR) {
                OBJECT_ERROR_TOOL (
                        TopMarkObject,
                        analysis_keyvalue_line,
                        "'\033[01;31m%s\033[0m' "
                        "不属于当前大标签的注册类型！已停止解析。原始字符串: "
                        "%s\n",
                        object_string_get_string (OBJECT_STRING (key)),
                        object_string_get_string (OBJECT_STRING (kvline)));
                object_unref (key);
                object_unref (value);
                return 1;
        }
        tmp = label_object_new ();
        label_object_set_type (tmp, value_type);
        tmp->key = object_reference_to (key, OBJECT_STRING);
        state    = label_object_analysis_value (tmp, value);
        if (state != 0) {
                OBJECT_ERROR_TOOL (
                        TopMarkObject,
                        analysis_keyvalue_line,
                        "解析值时出现错误，停止解析。原始字符串: "
                        "'\033[01;31m%s\033[0m'\n",
                        object_string_get_string (OBJECT_STRING (kvline)));
                object_unref (tmp);
                object_unref (key);
                object_unref (value);
                return 1;
        }
        top_mark_object_add_label (obj, tmp);
        object_unref (tmp);
        object_unref (key);
        object_unref (value);
        return 0;
}

void
top_mark_object_register_as_school_time_table (TopMarkObject* obj)
{
        if (!obj) {
                OBJECT_ERROR_TOOL (TopMarkObject,
                                   register_as_school_time_table,
                                   "传入对象为空！\n");
                return;
        }
        if (obj->label_table) {
                OBJECT_WARNING_TOOL (TopMarkObject,
                                     register_as_school_time_table,
                                     "对象已注册值类型！\n");
                return;
        }
        top_mark_object_register (obj, "Version", VALUE_TYPE_TEXT);
        top_mark_object_register (obj, "Start", VALUE_TYPE_DATE);
}

void
top_mark_object_register_as_student_info (TopMarkObject* obj)
{
        if (!obj) {
                OBJECT_ERROR_TOOL (TopMarkObject,
                                   register_as_school_time_table,
                                   "传入对象为空！\n");
                return;
        }
        if (obj->label_table) {
                OBJECT_WARNING_TOOL (TopMarkObject,
                                     register_as_school_time_table,
                                     "对象已注册值类型！\n");
                return;
        }
        top_mark_object_register (obj, "Student", VALUE_TYPE_TEXT);
        top_mark_object_register (obj, "Grade", VALUE_TYPE_TEXT);
        top_mark_object_register (obj, "Class", VALUE_TYPE_TEXT);
}

void
top_mark_object_register_as_course_info (TopMarkObject* obj)
{
        if (!obj) {
                OBJECT_ERROR_TOOL (TopMarkObject,
                                   register_as_school_time_table,
                                   "传入对象为空！\n");
                return;
        }
        if (obj->label_table) {
                OBJECT_WARNING_TOOL (TopMarkObject,
                                     register_as_school_time_table,
                                     "对象已注册值类型！\n");
                return;
        }
        top_mark_object_register (obj, "Name", VALUE_TYPE_TEXT);
        top_mark_object_register (obj, "Location", VALUE_TYPE_TEXT);
        top_mark_object_register (obj, "Type", VALUE_TYPE_TEXT);
        top_mark_object_register (obj, "Credit", VALUE_TYPE_TEXT);
        top_mark_object_register (obj, "Teacher", VALUE_TYPE_TEXT);
        top_mark_object_register (obj, "Week", VALUE_TYPE_NUMBER);
        top_mark_object_register (obj, "Section", VALUE_TYPE_NUMBER);
        top_mark_object_register (obj, "Day", VALUE_TYPE_NUMBER);
        top_mark_object_register (obj, "Date", VALUE_TYPE_DATE);
}
